package storage

import (
	"errors"
	"fmt"
	"gitee.com/kinwyb/workflow/public"
	"time"
)

type IStorage interface {
	// FlowSave 保存流
	FlowSave(nodes []Node, routeNodes []RouteNode, ctx *public.ContextValue) error
	// FlowQuery 查询一个流
	FlowQuery(flowID string) ([]Node, error)
	// RouteQuery 判断条件查询
	RouteQuery(routeID string) ([]RouteNode, error)
	// FlowNodeQuery 流程节点查询
	FlowNodeQuery(nodeID string) (Node, error)
	// WorkCreate 工作创建
	WorkCreate(work Work, detail []WorkDetail, ctx *public.ContextValue) error
	// WorkQueryByID 工作查询
	WorkQueryByID(workID string, ctx *public.ContextValue) (*Work, error)
	// WorkFlowSave 工作流保存
	WorkFlowSave(workFlow WorkFlow, ctx *public.ContextValue) error
	// WorkFlowQuery 工作流查询,workFlowCode 工作流编码,useStatus 工作流状态(-1=全部,0=未启用,1=启用)
	WorkFlowQuery(workFlowID string, workFlowCode string, useStatus int, ctx *public.ContextValue) []*WorkFlow
	// WorkNodeQueryByID 工作节点查询
	WorkNodeQueryByID(workDetailID string) (*WorkNode, error)
	// WorkNodeCompleteAndReturnNextWorkNodeID 工作节点完成并返回下一个工作节点ID
	WorkNodeCompleteAndReturnNextWorkNodeID(workNode *WorkNode, isPass bool, memo string, ctx *public.ContextValue) (string, error)
	// ActiveWorkNodeQueryByWorkID 根据工作ID查询激活的工作节点
	ActiveWorkNodeQueryByWorkID(workID string) (*WorkNode, error)
	// FlowNodeUpdate 流程节点更新
	FlowNodeUpdate(node Node, routeNodes []RouteNode, ctx *public.ContextValue) error
	// EnableWorkFlow 启用工作流
	EnableWorkFlow(workFlowID string, ctx *public.ContextValue) error
	// DisableWorkFlow 禁用工作流
	DisableWorkFlow(workFlowID string, ctx *public.ContextValue) error
	// FlowDel 工作流删除
	FlowDel(flowID string, ctx *public.ContextValue) error
	// WorkNodes 查询所有工作节点
	WorkNodes(workID string, ctx *public.ContextValue) ([]*WorkNode, error)
	// WaitDoWorkList 待工作列表
	WaitDoWorkList(workFlowCode string, userID string, ctx *public.ContextValue) ([]WorkNode, error)
	// UserGroupList 用户组列表
	UserGroupList(ctx *public.ContextValue) ([]string, error)
	// UserGroupUserIDQuery 用户组用户ID列表
	UserGroupUserIDQuery(userGroupName string, ctx *public.ContextValue) ([]string, error)
	// UserGroupAddUserID 用户组绑定用户
	UserGroupAddUserID(userGroupName string, userID string, ctx *public.ContextValue) error
	// UserGroupDelUserID 用户组移除用户
	UserGroupDelUserID(userGroupName string, userID string, ctx *public.ContextValue) error
	// NodeUserGroupCheckUser 检测用户是否全有操作当前节点
	NodeUserGroupCheckUser(nodeID string, userID string, ctx *public.ContextValue) bool
}

var storage IStorage

var NotSupportedErr = errors.New("没有存储支持")

// RegisterStorage 注册存储层
func RegisterStorage(stg IStorage) {
	storage = stg
}

// FlowSave 保存流
func FlowSave(nodes []Node, routeNodes []RouteNode, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.FlowSave(nodes, routeNodes, ctx)
}

// FlowQuery 查询一个流
func FlowQuery(flowID string, ctx *public.ContextValue) ([]Node, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	ret, err := storage.FlowQuery(flowID)
	if err != nil {
		return nil, err
	}
	if len(ret) < 1 {
		return nil, errors.New("流程不存在")
	}
	return ret, nil
}

// RouteQuery 判断条件查询
func RouteQuery(routeID string) ([]RouteNode, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.RouteQuery(routeID)
}

// WorkCreate 工作创建
func WorkCreate(work Work, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	if work.WorkFlowCode == "" {
		return errors.New("工作流编码不能为空")
	}
	if work.WorkID == "" {
		work.WorkID = public.IDGenIntString()
	}
	workFlowID, nodes, err := UseWorkFlowQueryFlowNode(work.WorkFlowCode, ctx)
	if err != nil {
		return err
	}
	work.WorkFlowID = workFlowID
	work.WorkStatus = 0
	var workDetials = make([]WorkDetail, len(nodes))
	startNodeID := ""
	for idx, node := range nodes {
		detail := WorkDetail{
			WorkDetailID:     public.IDGenIntString(),
			WorkID:           work.WorkID,
			NodeID:           node.NodeID,
			WorkDetailStatus: int(WorkDetailStatusSleep),
		}
		if node.NodeType == NodeTypeStart {
			startNodeID = node.NodeID
			detail.WorkDetailStatus = int(WorkDetailStatusEnd)
			detail.UpdateTime = time.Now().Format("2006-01-02 15:04:05")
			detail.UpdateUser = "系统自动"
		}
		workDetials[idx] = detail
	}
	if startNodeID == "" {
		return errors.New("工作流异常:无开始节点")
	}
	for idx, detail := range workDetials {
		if detail.NodeID == startNodeID {
			detail.WorkDetailStatus = int(WorkDetailStatusActive)
			workDetials[idx] = detail
			break
		}
	}
	return storage.WorkCreate(work, workDetials, ctx)
}

// WorkQueryByID 工作查询
func WorkQueryByID(workID string, ctx *public.ContextValue) (*Work, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.WorkQueryByID(workID, ctx)
}

// WorkFlowSave 工作流保存
func WorkFlowSave(workFlow WorkFlow, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.WorkFlowSave(workFlow, ctx)
}

// UseWorkFlowQueryFlowNode 使用中的工作流查询返回流节点
func UseWorkFlowQueryFlowNode(workFlowCode string, ctx *public.ContextValue) (string, []Node, error) {
	if storage == nil {
		return "", nil, NotSupportedErr
	}
	workFlows := storage.WorkFlowQuery("", workFlowCode, 1, ctx)
	if len(workFlows) < 1 {
		return "", nil, fmt.Errorf("无有效工作流")
	}
	nodes, err := storage.FlowQuery(workFlows[0].FlowID)
	if err != nil {
		return "", nil, err
	}
	return workFlows[0].WorkFlowID, nodes, nil
}

// WorkNodeQueryByID 工作节点信息查询
func WorkNodeQueryByID(workDetailID string, ctx *public.ContextValue) (*WorkNode, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.WorkNodeQueryByID(workDetailID)
}

// WorkNodeComplete 工作节点完成
func WorkNodeComplete(workNode *WorkNode, isPass bool, memo string, ctx *public.ContextValue) (string, error) {
	if storage == nil {
		return "", NotSupportedErr
	}
	switch WorkStatus(workNode.WorkStatus) {
	case WorkStatusEnd:
		return "", errors.New("流程已结束")
	case WorkStatusStop:
		return "", errors.New("流程已终止")
	}
	switch WorkDetailStatus(workNode.WorkDetailStatus) {
	case WorkDetailStatusEnd:
		return "", errors.New("流程节点已结束")
	case WorkDetailStatusStop:
		return "", errors.New("流程节点已终止")
	case WorkDetailStatusSleep:
		return "", errors.New("流程节点未激活")
	}
	return storage.WorkNodeCompleteAndReturnNextWorkNodeID(workNode, isPass, memo, ctx)
}

// ActiveWorkNodeQueryByWorkID 根据工作ID查询激活的工作节点
func ActiveWorkNodeQueryByWorkID(workID string) (*WorkNode, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.ActiveWorkNodeQueryByWorkID(workID)
}

// FlowNodeQuery 流程节点查询
func FlowNodeQuery(nodeID string) (Node, error) {
	if storage == nil {
		return Node{}, NotSupportedErr
	}
	return storage.FlowNodeQuery(nodeID)
}

// FlowNodeUpdate 流程节点更新
func FlowNodeUpdate(node Node, routeNodes []RouteNode, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.FlowNodeUpdate(node, routeNodes, ctx)
}

// EnableWorkFlow 启用工作流
func EnableWorkFlow(workFlowID string, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.EnableWorkFlow(workFlowID, ctx)
}

// DisableWorkFlow 禁用工作流
func DisableWorkFlow(workFlowID string, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.DisableWorkFlow(workFlowID, ctx)
}

// FlowDel 工作流删除
func FlowDel(flowID string, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.FlowDel(flowID, ctx)
}

// WorkNodes 查询所有工作节点
func WorkNodes(workID string, ctx *public.ContextValue) ([]*WorkNode, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.WorkNodes(workID, ctx)
}

// WaitDoWorkList 待工作列表
func WaitDoWorkList(workFlowCode string, userID string, ctx *public.ContextValue) ([]WorkNode, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.WaitDoWorkList(workFlowCode, userID, ctx)
}

// WorkFlowQuery 工作流查询,workFlowCode 工作流编码,useStatus 工作流状态(-1=全部,0=未启用,1=启用)
func WorkFlowQuery(workFlowID string, workFlowCode string, useStatus int, ctx *public.ContextValue) []*WorkFlow {
	if storage == nil {
		return nil
	}
	return storage.WorkFlowQuery(workFlowID, workFlowCode, useStatus, ctx)
}

// UserGroupList 用户组列表
func UserGroupList(ctx *public.ContextValue) ([]string, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.UserGroupList(ctx)
}

// UserGroupUserIDQuery 用户组用户ID列表
func UserGroupUserIDQuery(userGroupName string, ctx *public.ContextValue) ([]string, error) {
	if storage == nil {
		return nil, NotSupportedErr
	}
	return storage.UserGroupUserIDQuery(userGroupName, ctx)
}

// UserGroupAddUserID 用户组绑定用户
func UserGroupAddUserID(userGroupName string, userID string, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.UserGroupAddUserID(userGroupName, userID, ctx)
}

// UserGroupDelUserID 用户组移除用户
func UserGroupDelUserID(userGroupName string, userID string, ctx *public.ContextValue) error {
	if storage == nil {
		return NotSupportedErr
	}
	return storage.UserGroupDelUserID(userGroupName, userID, ctx)
}

// NodeUserGroupCheckUser 检测用户是否全有操作当前节点
func NodeUserGroupCheckUser(nodeID string, userID string, ctx *public.ContextValue) bool {
	if storage == nil {
		return false
	}
	return storage.NodeUserGroupCheckUser(nodeID, userID, ctx)
}
